package com.nulldev.util.osAPI.hardware.gpu;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.osAPI.OS;
import com.nulldev.util.processAPI.Processes;

public class GPUs {
	private static final Logger log = LoggerFactory.getLogger();

	public static GPU parse() {
		try {
			final String data = gpuName();
			final Vendor parseVendor = parseVendor(data);
			return new GPU(parseVendor, data);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static Vendor parseVendor(final String data) {
		final String[] items = data.split(" ");
		try {
			if (items[0].equals("Advanced") && items[1].equals("Micro") && items[2].equals("Devices,") && items[3].equals("Inc.")) {
				return Vendor.AMD;
			}
		} catch (Exception e) {
		}
		if (items[0].equals("NVIDIA")) {
			return Vendor.NVIDIA;
		} else if (items[0].equals("RADEON(tm)") || items[0].equals("Radeon(tm)") || items[0].equals("Radeon(TM)")) {
			return Vendor.RADEON;
		} else if (items[0].equals("AMD(tm)")) {
			return Vendor.AMD;
		} else if (items[0].equals("Intel(tm)")) {
			return Vendor.INTEL;
		} else if (data.contains("Intel Corporation")) {
			return Vendor.INTEL;
		} else if (data.contains("Intel Corporation") || (data.contains("Intel(R)") && data.contains("Graphics"))) {
			return Vendor.INTEL;
		} else {
			log.warn("Unknown vendor: " + data);
			return Vendor.OTHER;
		}
	}

	public static Vendor getVendor() {
		try {
			return parseVendor(gpuName());
		} catch (Exception e) {
			JVM.errorln(e);
			return Vendor.OTHER;
		}
	}

	public static String gpuName() throws Exception {
		if (OS.isWindows()) {
			final String out = Processes.execCmd("wmic path win32_VideoController get name");
			if (out.contains("NVIDIA")) {
				final String cleared = StringsUtil.filterStringS(out.substring(out.indexOf("NVIDIA")), 1);
				return cleared.substring(0, cleared.length() - 1);
				// return "Radeon(tm) RX 460";//cleared.substring(0, cleared.length() - 1);
			} else if (out.contains("Radeon(TM)")) {
//				final String cleared = StringsUtil.filterStringS(out.substring(out.indexOf("Radeon(TM)")), 1);
				return out.substring(out.indexOf("Radeon(TM)"), out.length() - 1);
			} else if (out.contains("Intel(R)")) {
				final String cleared = StringsUtil.filterStringS(out.substring(out.indexOf("Intel(R)")), 1);
				return cleared.substring(0, cleared.length() - 1);
			} else {
				log.warn("Unknown video controller: " + StringsUtil.cleanInvalidCharacters(out));
				return "N/A";
			}
		} else if (OS.isLinux()) {
			final String[] out = StringsUtil.byLineSepeartor(Processes.execCmd("lspci"));
			final String investigate = ArrayUtils.StringArrayUtils.find(out, "VGA compatible controller: ");
			try {
				final String[] gpuData = investigate.split("VGA compatible controller: ");
				final String filtered = gpuData[1];
				return filtered;
			} catch (Exception e) {
				JVM.errorln("[GPUUtil] An error occured while running 'lspci'.");
			}
		}
		JVM.errorln("[GPUUtil] Unsupported OS!");
		return "N/A";// throw new UnsupportedOperationException("Unsupported OS");
	}
}
